/*
 * Copyright (c) 2020-2021 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
 
#include <time.h>
#include <net/if.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <string.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>

#include "rtp.h"
#include "rtsp_log.h"
#include "securec.h"


#define RTP_HEADER_SIZE         12
#define RTP_MAX_PKT_SIZE        1400

int Rtp::UdpSendPacket(struct RtpPacket* rtpPacket, uint32_t dataSize)
{
	int ret;
	struct sockaddr_in addr;

	addr.sin_family = AF_INET;
	addr.sin_port = htons(port_);
	addr.sin_addr.s_addr = inet_addr(ip_);
#ifdef FRAME_DATA_DEBUG
	write(saveRtpFd_, (char*)rtpPacket, dataSize);
#endif
	rtpPacket->rtpHeader.seq = htons(rtpPacket->rtpHeader.seq);
	rtpPacket->rtpHeader.timestamp = htonl(rtpPacket->rtpHeader.timestamp);
	rtpPacket->rtpHeader.ssrc = htonl(rtpPacket->rtpHeader.ssrc);
	ret = sendto(sock_, (void*)rtpPacket, dataSize + RTP_HEADER_SIZE, 0,
			   (struct sockaddr*)&addr, sizeof(addr));
	if(ret < 0){
	   SAMPLE_ERROR("sendto");
	}
	rtpPacket->rtpHeader.seq = ntohs(rtpPacket->rtpHeader.seq);
	rtpPacket->rtpHeader.timestamp = ntohl(rtpPacket->rtpHeader.timestamp);
	rtpPacket->rtpHeader.ssrc = ntohl(rtpPacket->rtpHeader.ssrc);
	return ret;
}


int Rtp::UdpSendFrame(uint8_t *pNalBuf, int s32NalBufSize)
{
	char *pNaluPayload;
	int s32Bytes = 0;
	int s32Ret = 0;
	struct timeval stTimeval;
	uint8_t *pNaluCurr;
	int s32NaluRemain;
	unsigned char u8NaluBytes;
	static int seq = 0;
	static uint32_t timestamp = 0;
	int naluType = pNalBuf[0];
	int ret = 0;
	int sendBytes = 0;
	
	struct RtpPacket rtpPacket;

	rtpPacket.rtpHeader.csrcLen = 0;
	rtpPacket.rtpHeader.extension = 0;
	rtpPacket.rtpHeader.padding = 0;
	rtpPacket.rtpHeader.version = 2;
	
	rtpPacket.rtpHeader.payloadType = 96;
	
	rtpPacket.rtpHeader.ssrc = 10;
	
	rtpPacket.rtpHeader.timestamp = timestamp;
	timestamp += 90000/25;

	if (s32NalBufSize <= RTP_MAX_PKT_SIZE) {	
		//memcpy(rtpPacket.payload, pNalBuf, s32NalBufSize);
		if (memcpy_s(rtpPacket.payload, s32NalBufSize, pNalBuf, s32NalBufSize) != EOK) {
			SAMPLE_INFO("memcpy_s");	
			return -1;
		}
		//SAMPLE_ERROR("seq -> %d", seq);

		rtpPacket.rtpHeader.marker	 = 1;
		rtpPacket.rtpHeader.seq = seq++;
		ret = UdpSendPacket(&rtpPacket, s32NalBufSize);
		sendBytes += ret;
		SAMPLE_INFO("sendBytes->%d", sendBytes);
	   
	} else {
		int pktNum = s32NalBufSize / RTP_MAX_PKT_SIZE;		 
		int remainPktSize = s32NalBufSize % RTP_MAX_PKT_SIZE;
		int i, pos, head_len;

		head_len = 2;
		pos = head_len; 

		for(i = 0; i < pktNum; i++)
		{
			rtpPacket.rtpHeader.seq = seq++;
			
			rtpPacket.payload[0] = 49 << 1;
			rtpPacket.payload[1] = 1;
			rtpPacket.payload[2] = (naluType & 0x7E)>>1;
			if (i == 0) { 
				rtpPacket.rtpHeader.marker = 1;
				rtpPacket.payload[2] |= 0x80; // start
			}
			else if (remainPktSize == 0 && i == (pktNum - 1)){
				rtpPacket.rtpHeader.marker = 0;
				rtpPacket.payload[2] |= 0x40; // end
			}

			//memcpy(rtpPacket.payload + head_len + 1, pNalBuf+pos, RTP_MAX_PKT_SIZE);
			if (memcpy_s(rtpPacket.payload + head_len + 1, RTP_MAX_PKT_SIZE, pNalBuf+pos, RTP_MAX_PKT_SIZE) != EOK) {
				SAMPLE_INFO("memcpy_s");	
				return -1;
			}
			
			ret = UdpSendPacket(&rtpPacket, RTP_MAX_PKT_SIZE + head_len + 1);
			if (ret < 0) {
				SAMPLE_ERROR("rtpSendPacket is error");
				goto cleanup;
			}
			sendBytes += ret;
			pos += RTP_MAX_PKT_SIZE;
		}
		if (remainPktSize > 0)
		{
			{
				rtpPacket.payload[0] = 49 << 1;
				rtpPacket.payload[1] = 1;
				rtpPacket.payload[2] = (naluType & 0x7E)>>1;
				rtpPacket.payload[2] |= 0x40; // end
			}
			//memcpy(rtpPacket.payload + head_len + 1, pNalBuf + pos, remainPktSize);
			if (memcpy_s(rtpPacket.payload + head_len + 1, remainPktSize, pNalBuf+pos, remainPktSize) != EOK) {
				SAMPLE_INFO("memcpy_s");	
				return -1;
			}
			rtpPacket.rtpHeader.seq = seq++;
			ret = UdpSendPacket(&rtpPacket, remainPktSize+head_len+1);
			if(ret < 0)
			{
				SAMPLE_ERROR("rtpSendPacket is error");
				goto cleanup;
			}
			sendBytes += ret;
		}
		
	}
	
	return sendBytes;
cleanup:
	return 0;	
}


int Rtp::SetIpPort(char* ip, uint8_t ipLen, int port)
{
	//memcpy(ip_, ip, ipLen);
	if (memcpy_s(ip_, sizeof(ip_), ip, ipLen) != EOK) {
		SAMPLE_INFO("memcpy_s");	
		return -1;
	}
	port_ = port;
	SAMPLE_INFO("IP->%s,port->%d\n", ip_, port_);
	return 0;
}

int Rtp::UdpSocket(void)
{
	int ret;
	int s32Broadcast = 1;
	
	sock_ = socket(AF_INET, SOCK_DGRAM, 0);
	if (sock_ < 0) {
		SAMPLE_ERROR("SOCK");
		return -1;
	}

	ret = setsockopt(sock_, SOL_SOCKET, SO_BROADCAST, (char *)&s32Broadcast, sizeof(s32Broadcast));
	if (ret < 0) {
        SAMPLE_ERROR("setsockopt");
        return -1;
    }
    SAMPLE_INFO("<><><><>success creat RTP<><><><>");
    return 0;
}


int Rtp::UdpGetSocket(void)
{
	if (sock_ < 0) {
		SAMPLE_ERROR("sock_ < 0");
		return -1;
	}
	return sock_;
}

int Rtp::CloseUdpSocket(void)
{
	if (sock_ < 0) {
		SAMPLE_ERROR("sock_ < 0");
		return -1;
	}
	close(sock_);
	return 0;
}

